#ifndef __NET_SESSION_H__
#define __NET_SESSION_H__

#include <memory>
#include <mutex>

#include <boost/asio.hpp>

#include "google/protobuf/message.h"

#define MAX_WIRTE_BUFFER_SIZE 8192

class MessageParse;
class SessionMgr;
union MessageID;

enum SessionCreateType : uint16_t
{
    eSessionCreateNone,        // 未设置
    eSessionCreateListen,      // 负责监听的会话
    eSessionCreateAccepted,    // 远程连接过来的会话
    eSessionCreateConn,        // 主动连接的会话
};

enum SessionType : uint16_t
{
    eNormal = 0,
    eCmd    = 1,
    eGm     = 2,
    eGate   = 3,
};


struct ServerNetInfo;

class SessionCustomData
{
public:
    virtual void onSessionClose() = 0;
};

/**
 * @desc 网络会话类，每个会话类代表一个SOCKET连接
 * @auth Qiwei.Gu
 * @date 2015-03-21 17:38:53
 */
class Session : public std::enable_shared_from_this<Session>
{
public:
    friend class SessionMgr;

    /**
     * @desc 构造函数
     * @param ios Boost Asio 对象
     * @param sessionMgr 会话管理类
     * @auth Qiwei.Gu
     * @date 2015-03-21 17:40:00
     */
    explicit Session(boost::asio::io_service& ios,
                     const std::shared_ptr<SessionMgr>& sessionMgr,
                     const std::shared_ptr<ServerNetInfo>& netInfo,
                     SessionCreateType createType);

    virtual ~Session();

    /**
     * @desc 初始化
     * @auth Qiwei.Gu
     * @date 2015-04-04 12:51:19
     */
    bool initListen();
    bool initConn(bool async);

    /**
     * @desc 得到会话句柄
     * @auth Qiwei.Gu
     * @date 2015-03-26 23:08:51
     */
    int64_t getHandle();

    SessionCreateType getCreateType() { return createType_; }


    /**
     * @desc 返回asio socket对象
     * @auth Qiwei.Gu
     * @date 2015-03-21 17:47:09
     */
    boost::asio::ip::tcp::socket& getSocket() { return socket_; }

    /**
     * @desc 处理监听
     * @param
     * @auth Qiwei.Gu
     * @date 2015-04-04 11:12:56
     */
    void startAccept();

    /**
     * @desc 结束处理网络事件
     * @auth Qiwei.Gu
     * @date 2015-03-21 17:48:36
     */
    void stop();

    /**
     * @desc 检测连接是否已经连接
     * @auth Qiwei.Gu
     * @date 2015-05-05 18:18:21
     */
    bool isOpen();

    /**
     * @desc 向对方发送数据
     * @param buf 数据
     * @param size buf 长度
     * @auth Qiwei.Gu
     * @date 2015-04-12 01:47:09
     */
    bool sendData(const char* buf, std::size_t size);


    /**
     * @desc 向对方发送消息
     * @param msgID 消息ID
     * @param msg 消息内容
     * @auth Qiwei.Gu
     * @date 2015-04-12 01:47:09
     */
    bool sendMsg(const MessageID& msgID, google::protobuf::Message& msg);

    /**
     * @desc 向对方发送消息
     * @param msgID 消息ID
     * @param msg 消息内容
     * @auth Qiwei.Gu
     * @date 2015-04-12 01:47:09
     */
    bool sendMsg(uint16_t moduleType, uint16_t msgID, google::protobuf::Message& msg);

    /**
     * @desc 向对方发送消息
     * @param msgID 消息ID
     * @param msg 消息内容
     * @auth Qiwei.Gu
     * @date 2015-04-12 01:47:09
     */
    bool sendMsg(uint16_t moduleType, uint16_t msgID, const char* buf, std::size_t bufSize);

    /**
     * @desc 向对方发送消息
     * @param msgID 消息ID
     * @param msg 消息内容
     * @auth Qiwei.Gu
     * @date 2015-04-12 01:47:09
     */
    bool sendMsg(const MessageID& msgID, const char* buf, std::size_t bufSize);


    /**
     * @desc 分发消息
     * @param msgID 消息ID
     * @param msg 消息内容
     * @auth Qiwei.Gu
     * @date 2015-03-21 17:49:44
     */
    bool dispatchMessage(const MessageID& msgID, const google::protobuf::Message& msg);

    /**
     * @desc 网络配置
     * @auth Qiwei.Gu
     * @date 2015-04-19 00:13:40
     */
    const std::shared_ptr<ServerNetInfo>& getNetInfo() { return netInfo_; }

    /**
     * @desc 设置自定义数据
     * @auth Qiwei.Gu
     * @date 2015-04-22 13:39:20
     */
    void setCustomData(const std::shared_ptr<SessionCustomData>& customData) { customData_ =  customData; }

    /**
     * @desc 获取自定义数据
     * @auth Qiwei.Gu
     * @date 2015-04-22 13:40:43
     */
    const std::shared_ptr<SessionCustomData>& getCustomData() const { return customData_; }

    /**
     * @desc 查询解析器
     * @auth Qiwei.Gu
     * @date 2015-04-22 16:19:39
     */
    MessageParse& getMsgParse() const { return *msgParse_; }

    /**
     * @desc 开始处理网络事件
     * @auth Qiwei.Gu
     * @date 2015-03-21 17:48:03
     */
    virtual void startRead();

    /* std::shared_ptr<Session> getDownSession() { return downSession_; } */
    /* void setDownSession(const std::shared_ptr<Session>& session) { downSession_ = session; } */

protected:

    /**
     * @desc 处理读取的数据
     * @auth Qiwei.Gu
     * @date 2015-03-21 17:50:57
     */
    virtual void handleRead(const boost::system::error_code& e,
                            std::size_t bytes_transferred);

    /**
     * @desc 分发消息
     * @auth Qiwei.Gu
     * @date 2015-03-21 17:49:44
     */
    virtual bool dispatchMessage(const MessageID& msgID, const char* buf, std::size_t bufSize);



private:
    /**
     * @desc 处理网络连接
     * @auth Qiwei.Gu
     * @date 2015-03-21 18:05:11
     */
    void handleAccept(const boost::system::error_code& e,
                      const std::shared_ptr<Session>& accptSession);

    /**
     * @desc 处理异步连接
     * @auth Qiwei.Gu
     * @date 2015-04-04 14:00:05
     */
    void handleConn(const boost::system::error_code& e);

    /**
     * @desc 处理异步发送结果
     * @auth Qiwei.Gu
     * @date 2015-04-13 10:28:44
     */
    void handleSend(const boost::system::error_code& e,
                    std::size_t bytes_transferred);

    /**
     * @desc 设置会话句柄，默认为socket的句柄
     * @auth Qiwei.Gu
     * @date 2015-04-14 14:33:35
     */
    void updateHandle();

    /**
     * @desc 处理读数据错误
     * @auth Qiwei.Gu
     * @date 2015-04-22 17:28:28
     */
    void handleReadError(const boost::system::error_code& e);

protected:
    std::mutex mutex_;
    boost::asio::ip::tcp::socket socket_;
    std::weak_ptr<SessionMgr> sessionMgr_;
    std::shared_ptr<ServerNetInfo> netInfo_;
    boost::asio::ip::tcp::acceptor accept_;
    std::shared_ptr<Session> tmpAcceptedSession_;

    std::shared_ptr<MessageParse> msgParse_;       // 消息解析器

    boost::asio::streambuf writeBuffer_;           // 消息缓存
    // std::array<char, MAX_WIRTE_BUFFER_SIZE> writeBuffer_;           // 消息缓存
    boost::asio::deadline_timer reconnTimer_;      // 重连定时器
    int64_t handle_;
    SessionCreateType createType_;

    // std::shared_ptr<Session> downSession_;  // 向下转发消息的连接
    std::shared_ptr<SessionCustomData> customData_; // 自定义数据

    // std::map<uint64_t, std::shared_ptr<Session>> upSessions_;
};

#endif // __NET_SESSION_H__
